home *** CD-ROM | disk | FTP | other *** search
/ L' Effet Pommier 3 / L'Effet Pommier - Volume 03.iso / Programmation / gray image 2.1 / image.h < prev    next >
Text File  |  1995-05-30  |  20KB  |  630 lines

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /*
  3.  ************************************************************************
  4.  *
  5.  *               Grayscale Image
  6.  *
  7.  *   The image is represented as a Pixmap, i.e. a matrix of pixels
  8.  *    each of them specifies the gray level at a particular point
  9.  *
  10.  *    The header file defines arithmetical and all other operations
  11.  *          permitted on the grayscale image
  12.  *
  13.  * $Id: image.h,v 1.16 1995/03/17 18:00:57 oleg Exp oleg $
  14.  *
  15.  ************************************************************************
  16.  */
  17.  
  18. #ifndef __GNUC__
  19. #pragma once
  20. #endif
  21. #ifndef _image_h
  22. #define _image_h
  23.  
  24. #ifdef __GNUC__
  25. #pragma interface
  26. #endif
  27.  
  28. #include "myenv.h"
  29. #include "std.h"
  30.  
  31. typedef unsigned short GRAY;        // Pixel type
  32. typedef signed short GRAY_SIGNED;    // Pixel type, signed
  33. const int GRAY_MAXBIT = 8*sizeof(GRAY);    // Max no of bits per pixel
  34. const int GRAY_MAXVAL = ((1<<GRAY_MAXBIT)-1);
  35. typedef unsigned int card;        // Better be short, but compilers
  36.                     // seem to like 'int' better
  37.  
  38. class Rectangle;
  39. class rowcol;
  40. class Extrema;
  41. class EndianIn;
  42. class IMAGE;
  43. class FilterIt;
  44.  
  45.                 // A class to do a specific operation on 
  46.                 // every pixel element regardless of its
  47.                 // position. The matrix is traversed
  48.                 // row-by-row
  49. class PixelPrimAction
  50. {
  51.   friend class IMAGE;
  52.   virtual void operation(GRAY& pixel) = 0;
  53.                 // Those are'n implemented; but since they're
  54.                 // private, it forbids the assignement
  55. //  PixelPrimAction(const PixelPrimAction&);
  56.   PixelPrimAction& operator= (const PixelPrimAction&);
  57. };
  58.  
  59.                 // A class to do a specific operation on 
  60.                 // every matrix element as the matrix
  61.                 // is efficiently traversed (row-by-row)
  62. class PixelAction
  63. {
  64.   friend class IMAGE;
  65.   virtual void operation(GRAY& pixel) = 0;
  66.  
  67. protected:
  68.   card nrows, ncols;        // These are set up by IMAGE::apply() function
  69.                 // and available to PixelAction::operation()
  70.   card row, col;        // position of the element being passed to
  71.                 // 'operator()'
  72.  
  73.  
  74. private:            // Those are'n implemented; but since they're
  75.                 // private, it forbids the assignement
  76. //  PixelAction(const PixelAction&);
  77.   PixelAction& operator= (const PixelAction&);
  78. };
  79.  
  80.                 // Lazy image constructor
  81.                 // It's highly recommended a function never
  82.                 // return IMAGE itself. Use LazyImage
  83.                 // instead
  84. class LazyImage
  85. {
  86.   friend class IMAGE;
  87.   virtual void fill_in(IMAGE& im) const = 0;
  88.  
  89.   LazyImage(const LazyImage&);        // Don't implement to forbid assignment
  90.   LazyImage& operator = (const LazyImage&);
  91.  
  92. protected:
  93.   card nrows, ncols, depth;
  94. public:
  95.   LazyImage(const card _nrows, const card _ncols, const card _depth)
  96.     : nrows(_nrows), ncols(_ncols), depth(_depth) {}
  97. };
  98.  
  99. class IMAGE
  100. {
  101.   friend class Rectangle;
  102.   friend class Extrema;
  103.   friend class FilterIt;
  104.  
  105. private:            // Private part
  106.   int valid_code;            // Validation code
  107.   enum { IMAGE_val_code = 577767 };    // Image validation code
  108.   card ncols;                // Image width in pixels
  109.   card nrows;                // Image height in pixels
  110.   unsigned long int npixels;        // Total no of pixels in the image
  111.   char * name;                // Image name
  112.   card bits_per_pixel;            // Image depth
  113.   GRAY ** scanrows;            // scanrows[i] = &pixels[i,0]
  114.   GRAY * pixels;            // pixels[i,j] is the
  115.                       // pixel value at point (i,j)
  116.                     // Pixels are ordered in rows
  117.  
  118.   void allocate(const card nrows, const card ncols, const card depth);
  119.  
  120.   void _expand(const IMAGE& prototype);    // Expand the prototype twice
  121.   void _shrink(const IMAGE& prototype);    // Shrink the prototype twice
  122.  
  123.                     // The following functions create an
  124.                     // image from a particular file
  125.                     // format. They call allocate()
  126.                     // to allocate the image data and
  127.                     // then read the data. The functions
  128.                     // are private to an IMAGE(file_name)
  129.                     // constructor and should be used
  130.                     // only by it
  131.   void read_xwd(EndianIn& file, const bool verbose); // read an X Window dump
  132.   void read_pgm(EndianIn& file, const bool verbose);// read a Portable GrayMap
  133.   void read_tiff(EndianIn& file, const bool verbose);    // read TIFF
  134.  
  135. public:            // Public interface
  136.   
  137.                 // Constructors and destructors
  138.                       // Make a blank image
  139.   IMAGE(const card nrows, const card ncols, const card depth);
  140.   IMAGE(const IMAGE& image);        // Make a new blank image like 
  141.                     // Read an image from the file
  142.                     // Attempts to detect the file format
  143.   IMAGE(const char * file_name,const bool print_header_info = false);
  144.   IMAGE(const Rectangle& area);        // Make an image from a rect area
  145.                     // of another image
  146.  
  147.                     // Construct an image applying a spec
  148.                     // operation to the prototype
  149.   enum IMAGE_CREATORS_1op { Expand, Shrink };
  150.   IMAGE(const IMAGE_CREATORS_1op op, const IMAGE& prototype);
  151.  
  152.   IMAGE(const LazyImage& lazy_constructor);//Make an image using given recipe
  153.  
  154.   ~IMAGE(void);
  155.  
  156.   void is_valid(void) const
  157.   { assure(valid_code == IMAGE_val_code,"Invalid image"); }
  158.  
  159.                 // Status
  160.   card q_nrows() const            { return nrows; }
  161.   card q_ncols() const            { return ncols; }
  162.   card q_depth() const            { return bits_per_pixel; }
  163.   unsigned long int q_npixels() const    { return npixels; }
  164.   const char * q_name() const          { return name; } 
  165.   void set_name(const char * new_name);    
  166.  
  167.                 // Individual pixel manipulations
  168.   const GRAY operator () (const card row, const card col) const;
  169.   GRAY& operator () (const card row, const card col);
  170.   const GRAY operator () (const rowcol pos) const;
  171.   GRAY& operator () (const rowcol pos);
  172.   void  sure_within(const rowcol pos) const;    // Make sure the pos
  173.                         // is within the image
  174.  
  175. // Row Column, Square operations
  176.  
  177.                 // Image-scalar operations
  178.  
  179.                 // Find out if the predicate
  180.                 // "(signed)pixel op val" is true for ALL
  181.                 // pixels of the image?
  182.   bool operator ==  (const int val) const;    // ? (signed)pixels == val
  183.   bool operator !=  (const int val) const;    // ? (signed)pixels != val
  184.   bool operator <   (const int val) const;    // ? (signed)pixels <  val
  185.   bool operator <=  (const int val) const;    // ? (signed)pixels <= val
  186.   bool operator >   (const int val) const;    // ? (signed)pixels >  val
  187.   bool operator >=  (const int val) const;    // ? (signed)pixels >= val
  188.  
  189.                 // Modify every element of the
  190.                 // image according to the operation
  191.   IMAGE& operator =   (const int val);        // Assignment to all the pixels
  192.   IMAGE& operator -=  (const int val);        // Diminish the brightness
  193.   IMAGE& operator +=  (const int val);        // Increase the brightness
  194.   IMAGE& operator *=  (const int val);
  195.   IMAGE& operator |=  (const int val);        // OR
  196.   IMAGE& operator &=  (const int val);        // AND
  197.   IMAGE& operator ^=  (const int val);        // XOR
  198.   IMAGE& operator <<= (const int val);        // Shift all the pixels
  199.   IMAGE& operator >>= (const int val);        // Shift all the pixels
  200.  
  201.  
  202.                 // Single image operations
  203.   IMAGE& clear(void);            // Clear the image
  204.   IMAGE& invert(void);            // Invert the image
  205.   IMAGE& abs(void);            // pixel = |(signed)pixel|
  206.   IMAGE& clip_to_intensity_range(void); // Clip pixel values to
  207.                     // [0,1<<bits_per_pixel-1]
  208.   IMAGE& normalize_for_display(void);    // Normalize pixel values to be
  209.                     // in range 0..1<<bits_per_pixel-1
  210.   IMAGE& equalize(const int no_grays);    // Perform the histogram equalization
  211.  
  212.   IMAGE& apply(PixelPrimAction& action);// Apply a user-defined action
  213.   IMAGE& apply(PixelAction& action);    // to each pixel
  214.  
  215.                 // Estimate the norm of the (signed) image
  216.   double norm_1(void)     const;    // SUM{ |(signed)pixel[i,j]| }
  217.   double norm_2_sqr(void) const;    // SUM{ (signed)pixel[i,j]^2 }
  218.   int    norm_inf(void)   const;    // MAX{ |(signed)pixel[i,j]| }
  219.  
  220.                 // Two images operations
  221.   IMAGE& operator = (const IMAGE& source);    // Assignment
  222.                     // Assign another to '*this' resizing
  223.   IMAGE& coerce(const IMAGE& another);    // '*this' as necessary to fit (by
  224.                     // not necessarily int factor!)
  225.   friend bool operator == (const IMAGE& im1, const IMAGE& im2);
  226.   friend void compare(const IMAGE& im1, const IMAGE& im2, 
  227.               const char * title);
  228.   friend inline void are_compatible(const IMAGE& im1, const IMAGE& im2);
  229.  
  230.                           // Arithmetics
  231.   IMAGE& operator += (const IMAGE& im);
  232.   IMAGE& operator -= (const IMAGE& im);
  233. //??  IMAGE& add(IMAGE& target, const int scalar,const IMAGE& source);
  234.                         // Shift the source to 'pos'
  235.                         // clip if necessary
  236.                         // multiply by scalar
  237.                         // and add
  238. //  IMAGE& shift_clip_add(rowcol pos, const int scalar, const IMAGE& source);
  239.  
  240.                         // Logic
  241.   IMAGE& operator |= (const IMAGE& im);
  242.   IMAGE& operator &= (const IMAGE& im);
  243.   IMAGE& operator ^= (const IMAGE& im);
  244.  
  245.                         // Scalar product
  246.   friend double operator * (const IMAGE& im1, const IMAGE& im2);
  247.  
  248.                 // Estimate the norm of the difference 
  249.                 // between two (signed) image
  250.                     // SUM{ |(signed)pixel[i,j]| }
  251.   friend double norm_1(const IMAGE& im1, const IMAGE& im2);
  252.                     // SUM{ (signed)pixel[i,j]^2 }
  253.   friend double norm_2_sqr(const IMAGE& im1, const IMAGE& im2);
  254.                     // MAX{ |(signed)pixel[i,j]| }
  255.   friend int    norm_inf(const IMAGE& im1, const IMAGE& im2);
  256.  
  257.  
  258.                 // I/O: write, read, display, print info
  259.                       // Write to a file
  260.                     // "| command name" is OK as a file
  261.                     // name
  262.   void write(const char * file_name,const char * title = "") const
  263.           { write_xwd(file_name,title); }
  264.                     // Write an X window dump
  265.   void write_xwd(const char * file_name,const char * title = "") const;
  266.                     // Write a Portable GrayMap
  267.   void write_pgm(const char * file_name,const char * title = "") const;
  268.                     // Write a TIFF file
  269.   void write_tiff(const char * file_name,const char * title = "") const;
  270.   void display(const char * title) const;
  271.   void info(void) const;        // Print the info about the image
  272.   void print(const char * title) const;    // Print the image as a table
  273.  
  274.                 // Clip a square area of the image
  275.   Rectangle    square_of (const card size, const rowcol pos);
  276.                 // Clip a rectangular area of the image
  277.                 // specified by the coordinates of
  278.                 // the upper-left and lower-right corners
  279.   Rectangle    rectangle (const rowcol uppleft, const rowcol lowright);
  280. };
  281.  
  282. /*
  283.  *------------------------------------------------------------------------
  284.  *        Position specification and operations on it
  285.  */
  286.  
  287. class rowcol {            // Specifying the row/col position
  288.   friend class Extrema;
  289.  
  290. protected:
  291.   short int row_val;            // both row, col start from 0
  292.   short int col_val;
  293.  
  294. public:
  295.                     // Constructors
  296.   rowcol(const int row, const int col)     : row_val(row), col_val(col) {}
  297. //??  rowcol(void)                : row_val(-1), col_val(-1) {}
  298.  
  299.   card row(void) const            { return row_val; }
  300.   card col(void) const            { return col_val; }
  301.  
  302.   bool operator == (const rowcol& pos) const
  303.       { return *((long int *)this) == *((long int *)&pos); }
  304. //    { return memcmp(this,&pos,sizeof(rowcol)); }
  305.  
  306.                     // Offset the current position
  307.   rowcol& operator += (const rowcol& pos)
  308.       { row_val += pos.row_val; col_val += pos.col_val; return *this; }
  309.   rowcol& operator -= (const rowcol& pos)
  310.       { row_val -= pos.row_val; col_val -= pos.col_val; return *this; }
  311.  
  312.   friend inline rowcol operator + (const rowcol& pos1, const rowcol& pos2);
  313.   friend inline rowcol operator - (const rowcol& pos1, const rowcol& pos2);
  314.  
  315.                     // Scale the current position
  316.   rowcol& operator *= (const int scalef)
  317.       { row_val *= scalef; col_val *= scalef; return *this; }
  318.  
  319.   friend inline rowcol operator *  (const rowcol& pos, const int scalef);
  320.   friend inline rowcol operator << (const rowcol& pos, const int shiftf);
  321.   friend inline rowcol operator >> (const rowcol& pos, const int shiftf);
  322. };
  323.  
  324. inline rowcol operator + (const rowcol& pos1, const rowcol& pos2)
  325.     { return rowcol(pos1.row_val+pos2.row_val, pos1.col_val+pos2.col_val);}
  326. inline rowcol operator - (const rowcol& pos1, const rowcol& pos2)
  327.     { return rowcol(pos1.row_val-pos2.row_val, pos1.col_val-pos2.col_val);}
  328.  
  329. inline rowcol operator *  (const rowcol& pos, const int scalef)
  330.     { return rowcol(pos.row_val*scalef, pos.col_val*scalef); }
  331. inline rowcol operator >> (const rowcol& pos, const int shiftf)
  332.     { return rowcol(pos.row_val >> shiftf, pos.col_val >> shiftf); }
  333. inline rowcol operator << (const rowcol& pos, const int shiftf)
  334.     { return rowcol(pos.row_val << shiftf, pos.col_val << shiftf); }
  335.  
  336.                 // This is only a specification of a rectangle
  337.                 // area
  338. class rectarea
  339. {
  340.   rowcol upperleft;
  341.   rowcol lowright;
  342. public:
  343.                 // Specify the rect area by the coordinates of
  344.                 // the upper-left and lower-right corners
  345.   rectarea(const rowcol _ul, const rowcol _lr) : 
  346.     upperleft(_ul), lowright(_lr) {}
  347.   
  348. };
  349.  
  350. class Extrema            // Find min/max values of the (signed) image
  351. {
  352.   GRAY_SIGNED max_value;        // Max pixel value in the image
  353.   GRAY_SIGNED min_value;        // Min pixel value in the image
  354.  
  355.   rowcol      max_pixel;        // Position of the largest pixel
  356.   rowcol      min_pixel;        // Position of the smallest pixel
  357.  
  358. public:
  359.   Extrema(const IMAGE& image);        // Find extreme pixels of the image
  360.  
  361.   GRAY_SIGNED max(void) const        { return max_value; }
  362.   GRAY_SIGNED min(void) const        { return min_value; }
  363.  
  364.   const rowcol& loc_max(void)        { return max_pixel; }
  365.   const rowcol& loc_min(void)        { return min_pixel; }
  366. };
  367.  
  368. /*
  369.  *------------------------------------------------------------------------
  370.  *         Dealing with the rectangular area of the image
  371.  */
  372.  
  373. class Rectangle
  374. {
  375.   friend class IMAGE;
  376.  
  377.   IMAGE&    image;        // The image I'm a rectangle of
  378.   card        nrows;        // Dimension of the rectangle
  379.   card         ncols;
  380.   GRAY *    ptr;        // Pointer to the upper left corner of 
  381.                 // the rectangle
  382.   int        inc_to_nextrow;    // inc_to_nextrow = p' - p =
  383.                   //           = image.ncols - ncols
  384.                 // where
  385.                 // p = ptr + ncols points to the pixel
  386.                 // just beyond the current scanline of
  387.                 // the Rectangle
  388.                 // p' = (ptr - col) + image.ncols + col
  389.                 // points to the first pixel of the next
  390.                 // scanline of the rectangtle
  391.                 // col tells the column of the upper left
  392.                 // corner of the rectangle within the image
  393.  
  394.                 // Private constructor
  395.                   // Note these are private constructors to
  396.                 // be used with IMAGE::square_of/rectangle
  397.                 // functions
  398.   Rectangle
  399.     (IMAGE& im, const card size, const rowcol pos);
  400.   Rectangle
  401.     (IMAGE& im, const rowcol uppleft, const rowcol lowright);
  402.  
  403.   public:
  404.                 // Note how to construct square area of
  405.                 // the image 'im':
  406.                 //    im.square_of(10,rowcol(1,5))
  407.                 // and rectangular area
  408.                 //     im.rectangle(rowcol(0,1),rowcol(4,5))
  409.  
  410.   Rectangle (IMAGE& im);        // Treat entire image as a rectangle
  411.                     // Assign a value to all the pixels
  412.                     // in the rectangle area
  413.   Rectangle& operator  = (const int val);
  414.                       // Modify the pixels in the rectangle
  415.                     // area
  416.   Rectangle& operator +=  (const int val);
  417.   Rectangle& operator -=  (const int val);
  418.   Rectangle& operator *=  (const int val);
  419.   Rectangle& operator |=  (const int val);
  420.   Rectangle& operator &=  (const int val);
  421.   Rectangle& operator ^=  (const int val);
  422.   Rectangle& operator <<= (const int val);
  423.   Rectangle& operator >>= (const int val);
  424.  
  425.                     // Copy a rectangle a_rect into the
  426.                     // rectangular area of the image
  427.   Rectangle& operator = (const Rectangle& a_rect);
  428.  
  429.                       // Get a total sum of all the pixels
  430.   friend double sum_over(const Rectangle& sa);
  431. };
  432.  
  433. /*
  434.  *------------------------------------------------------------------------
  435.  *            Some service procedures
  436.  */
  437.  
  438. inline
  439. int log2(            // Find a binary logarithm of n
  440.     const int n )        // and check that n is a power of two
  441. {
  442.   register int i,k;
  443.  
  444.   assure(n > 0, "log2: the argument's got to be positive!");
  445.  
  446.   for(n & 0xff ? k=0,i=1 : k=8,i=256; i < n; k++, i*=2)
  447.     ;
  448.   if( i != n )
  449.     _error("log2: the argument %d has got to be an exact power of two",n);
  450.  
  451.   return k;
  452. }
  453.  
  454. inline
  455. int exp2(const int k)            // Compute 2^k, k>=0
  456. {
  457.   assure(k >= 0, "exp2: the argument may not be negative!");
  458.   if( k > (signed)sizeof(int)*8-1 )
  459.     _error("exp2: the exponent %d is too big",k);
  460.  
  461.   return 1<<k;
  462. }
  463.  
  464. inline                    // return b * round( a/b )
  465. int round_to_even_multiple(const int a, const int b)
  466. {
  467.   assert( b > 0 );
  468.   register int rem = a % b;
  469.   if( 2*rem < b )
  470.     return a - rem;
  471.   else
  472.     return a + b - rem;
  473. }
  474.  
  475.                 // Service functions (useful in the
  476.                 // verification code). They print some detail
  477.                 // info if the validation condition fails
  478. void verify_pixel_value(const IMAGE& im, const GRAY val);
  479.  
  480. /*
  481.  *------------------------------------------------------------------------
  482.  *            Inline Image Procedures
  483.  */
  484.  
  485. inline IMAGE::IMAGE(const card no_rows, const card no_cols, const card depth)
  486. {
  487.   allocate(no_rows,no_cols,depth);
  488. }
  489.  
  490.                     // Make a new image like the
  491. inline IMAGE::IMAGE(const IMAGE& old)    // old one
  492. {
  493.   allocate(old.nrows,old.ncols,old.bits_per_pixel);
  494. }
  495.  
  496.  
  497. inline IMAGE::IMAGE(const LazyImage& lazy_constructor)
  498. {
  499.   allocate(lazy_constructor.nrows,lazy_constructor.ncols,
  500.        lazy_constructor.depth);
  501.   lazy_constructor.fill_in(*this);
  502. }
  503.  
  504. inline GRAY& IMAGE::operator () (const card row, const card col)
  505. {
  506.   is_valid();
  507.   if( row >= nrows )
  508.     _error("Row index %d is out of image boundaries [0,%d]",row,nrows-1);
  509.   if( col >= ncols )
  510.     _error("Col index %d is out of image boundaries [0,%d]",col,ncols-1);
  511.   
  512.   return (scanrows[row])[col];
  513. }
  514.  
  515. inline const GRAY IMAGE::operator () (const card row, const card col) const
  516. { return (*(IMAGE *)this).operator()(row,col); }
  517.  
  518. inline const GRAY IMAGE::operator () (const rowcol pos) const
  519. {
  520.   return operator()(pos.row(),pos.col());
  521. }
  522.  
  523. inline GRAY& IMAGE::operator () (const rowcol pos)
  524. {
  525.   return operator()(pos.row(),pos.col());
  526. }
  527.                     // Make sure the pos is within the
  528.                     // image
  529. inline void  IMAGE::sure_within(const rowcol pos) const
  530. {
  531.   is_valid();
  532.   if( pos.row() >= nrows )
  533.     _error("Row index %d is out of image boundaries [0,%d]",pos.row(),nrows-1);
  534.   if( pos.col() >= ncols )
  535.     _error("Col index %d is out of image boundaries [0,%d]",pos.col(),ncols-1);
  536. }
  537.  
  538. inline IMAGE& IMAGE::clear(void)    // Clean the image
  539. {
  540.   is_valid();
  541.   memset(pixels,0,npixels*sizeof(GRAY));
  542.   return *this;
  543. }
  544.  
  545. inline IMAGE& IMAGE::invert(void)    // Invert the image
  546. {
  547.   is_valid();
  548.   return (*this ^= ((1<<bits_per_pixel)-1));
  549. }
  550.  
  551. inline void are_compatible(const IMAGE& im1, const IMAGE& im2)
  552. {
  553.   im1.is_valid();
  554.   im2.is_valid();
  555.   
  556.   if( im1.ncols != im2.ncols || im1.nrows != im2.nrows )
  557.     _error("The image %dx%d and the image %dx%d have different sizes",
  558.        im1.nrows,im1.ncols,im2.nrows,im2.ncols);
  559. }
  560.  
  561.  
  562.                 // Apply a user-defined action to each pixel
  563. inline IMAGE& IMAGE::apply(PixelPrimAction& action)
  564. {
  565.   is_valid();
  566.   for(register GRAY *pp=pixels; pp < pixels+npixels; pp++)
  567.     action.operation(*pp);
  568.  
  569.   return *this;
  570. }
  571.  
  572.                 // Construct a square rectangle
  573. inline Rectangle::Rectangle
  574.     (IMAGE& im, const card sq_size, const rowcol pos)
  575.     : image(im), nrows(sq_size), ncols(sq_size)
  576. {
  577.   image.is_valid();
  578.  
  579.   if( pos.row() >= image.nrows ||
  580.       pos.row() + nrows > image.nrows ||
  581.       pos.col() >= image.ncols ||
  582.       pos.col() + ncols > image.ncols )
  583.     _error("Square area (left upper point [%d,%d], size %d)\n"
  584.        "is not within the image %dx%d",
  585.        pos.row(),pos.col(),sq_size,image.nrows,image.ncols);
  586.  
  587.   ptr  = &(image.scanrows[pos.row()][pos.col()]);
  588.   inc_to_nextrow = image.ncols - ncols;
  589. }
  590.  
  591.                 // Clip a square area from the image
  592. inline Rectangle IMAGE::square_of(const card size, const rowcol pos)
  593. { return Rectangle(*this, size, pos); }
  594.  
  595.  
  596.                 // Make a rectangle with upper left corner
  597.                 // at uppleft position and lower right corner
  598.                 // at lowright position
  599. inline Rectangle::Rectangle
  600.     (IMAGE& im, const rowcol uppleft, const rowcol lowright)
  601.     : image(im), nrows(lowright.row()-uppleft.row()+1), 
  602.                  ncols(lowright.col()-uppleft.col()+1)
  603. {
  604.   image.is_valid();
  605.  
  606.   image.sure_within(uppleft);
  607.   image.sure_within(lowright);
  608.  
  609.   ptr  = &(image.scanrows[uppleft.row()][uppleft.col()]);
  610.   inc_to_nextrow = image.ncols - ncols;
  611. }
  612.  
  613.  
  614.                 // Clip a rectangular area from the image
  615. inline Rectangle IMAGE::rectangle(const rowcol uppleft,const rowcol lowright)
  616. { return Rectangle(*this, uppleft, lowright); }
  617.  
  618.  
  619.                 // Treat the entire image as a rectangular area
  620. inline Rectangle::Rectangle (IMAGE& im)
  621.     : image(im), nrows(im.nrows), ncols(im.ncols)
  622. {
  623.   image.is_valid();
  624.  
  625.   ptr  = image.pixels;
  626.   inc_to_nextrow = 0;
  627. }
  628.  
  629. #endif
  630.